﻿#include "IPCCom.h"
#include <QDataStream>
#include <QFile>
#include <QDebug>

IPCCom::IPCCom(const QString &serverName, QObject *parent)
    : QObject(parent)
    , m_serverName(serverName)
{
}

IPCCom::~IPCCom()
{
    close();
}

bool IPCCom::open()
{
    if (QFile::exists(m_serverName)) QFile::remove(m_serverName);
    m_server = new QLocalServer(this);
    connect(m_server, &QLocalServer::newConnection, this, &IPCCom::onNewConnection);
    if (!m_server->listen(m_serverName)) {
        emit errorOccurred(tr("Server listen failed: %1").arg(m_server->errorString()));
        return false;
    }
    return true;
}

void IPCCom::close()
{
    if (m_socket) {
        m_socket->disconnectFromServer();
        m_socket->deleteLater();
        m_socket = nullptr;
    }
    if (m_server) {
        m_server->close();
        m_server->deleteLater();
        m_server = nullptr;
    }
}

bool IPCCom::isOpen() const
{
    return m_server && m_server->isListening();
}

QString IPCCom::serverName() const
{
    return m_serverName;
}

bool IPCCom::send(const QByteArray &data)
{
    if (!m_socket) return false;

    QByteArray all = data.endsWith('\n') ? data : (data + "\n");
    qint64 written = m_socket->write(all);
    m_socket->flush();
    return written == all.size();
}

void IPCCom::onNewConnection()
{
    if (!m_server) return;
    QLocalSocket *client = m_server->nextPendingConnection();
    if (m_socket) {
        // 已有一个连接
        client->disconnectFromServer();
        client->deleteLater();
        return;
    }
    m_socket = client;
    connect(m_socket, &QLocalSocket::readyRead, this, &IPCCom::onReadyRead);
    connect(m_socket, &QLocalSocket::disconnected, this, &IPCCom::onDisconnected);
    connect(m_socket, qOverload<QLocalSocket::LocalSocketError>(&QLocalSocket::error), this, &IPCCom::onError);
    emit connected();
}

void IPCCom::onReadyRead()
{
    onDataReceived(m_socket->readLine());
}

void IPCCom::onDisconnected()
{
    emit disconnected();
    if (m_socket) {
        m_socket->deleteLater();
        m_socket = nullptr;
    }
}

void IPCCom::onError(QLocalSocket::LocalSocketError err)
{
    Q_UNUSED(err)
    emit errorOccurred(m_socket->errorString());
}
